package com.jack.payment.controller.admin.noauth;

import com.jack.payment.cache.CacheRedisServiceImpl;
import com.jack.payment.constant.ResultHintConstant;
import com.jack.payment.constant.SettingRuleConstant;
import com.jack.payment.constant.enums.AccountVerifyCodeEnum;
import com.jack.payment.constant.enums.LoginMethodEnum;
import com.jack.payment.entity.business.SendEmailBo;
import com.jack.payment.entity.common.BusinessException;
import com.jack.payment.entity.common.CommonAskHead;
import com.jack.payment.entity.common.CommonAskParam;
import com.jack.payment.entity.common.CommonResult;
import com.jack.payment.entity.generate.user.UserAuthModel;
import com.jack.payment.entity.generate.user.UserDeviceModel;
import com.jack.payment.entity.generate.user.UserModel;
import com.jack.payment.entity.generate.user.UserSettingModel;
import com.jack.payment.entity.request.BasicAccountModel;
import com.jack.payment.entity.result.LoginSuccessModel;
import com.jack.payment.rabbitmq.RabbitQueueSendUtil;
import com.jack.payment.service.basic.impl.UserServiceImpl;
import com.jack.payment.util.auth.AuthUtils;
import com.jack.payment.util.common.StringUtil;
import com.jack.payment.util.generate.UserGenerate;
import com.jack.payment.util.redis.RedisUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@Tag(name = "登录注册")
@RequestMapping("/api/v1/account")
public class NotUserController {
    private Logger log = LoggerFactory.getLogger(NotUserController.class);

    @Autowired
    private UserServiceImpl userService;
    @Autowired
    private UserGenerate userGenerate;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private CacheRedisServiceImpl cacheRedisService;
    @Autowired
    private RabbitQueueSendUtil rabbitQueueSendUtil;

    /**
     * 登录成功后
     * @param userId
     * @param common
     */
     private void loginSuccess(String userId, CommonAskHead common) throws BusinessException {
        rabbitQueueSendUtil.LoginSuccessQueueMessage(
                new UserDeviceModel().builder()
                        .userId(userId)
                        .deviceId(common.getDeviceId())
                        .deviceModel(common.getDeviceModel())
                        .appVersion(common.getOsAppVersion())
                        .ipAddress(common.getIpAddress())
                        .lastOneTime(common.getCurrentTime())
                        .build()
        );

    }

    @Operation(summary = "发送送验证码 ✔")
    @RequestMapping(value = "sendVerifyCode", method = {RequestMethod.POST})
    @ResponseBody
    public CommonResult sendVerifyCode(@RequestBody CommonAskParam<BasicAccountModel.SendVerifyCodeModel> data) throws BusinessException {
        BasicAccountModel.SendVerifyCodeModel accountModel = data.getData();
        UserModel getUser = userService.getAppointUserAccountInfo(
                accountModel.getAccount(),
                accountModel.getSource()
        );
        AccountVerifyCodeEnum verifyCodeEnum = AccountVerifyCodeEnum.getAccountVerifyCodeEnum(accountModel.getType());
        // 获取redis 中的详细键值对
        SendEmailBo sendEmail = userService.getRedisVerifyKeyInfo(
                getUser,
                accountModel,
                verifyCodeEnum
        );
        String verifyCodeContent = redisUtil.get(sendEmail.getRedisKey());
        if (!StringUtil.isEmpty(verifyCodeContent)) {
            log.warn("验证码已发送, {} 账户在尝试重复发送", accountModel.getAccount());
            throw new BusinessException();
        }
        String verifyCode = StringUtil.verifyCode();
        userService.sendVerifyCodeService(sendEmail, verifyCode);
        redisUtil.set(sendEmail.getRedisKey(), verifyCode, 60 * 5);
        return CommonResult.ok();
    }


    @Operation(summary  = "登录")
    @RequestMapping(value = "login", method = {RequestMethod.POST})
    @ResponseBody
    public CommonResult login(@RequestBody @Validated CommonAskParam<BasicAccountModel> data) throws BusinessException{
        BasicAccountModel basicAccountModel = data.getData();
        String basicRedisKey = SettingRuleConstant.FAIL_LOGIN_COUNT;
        String getFailCount = redisUtil.get(basicRedisKey + basicAccountModel.getAccount());
        if (!StringUtil.isEmpty(getFailCount)) {
            if(Integer.valueOf(getFailCount) > (Integer) cacheRedisService.getCacheRuleContent(basicRedisKey)){
                return CommonResult.error();
            }
        }
        UserModel getUser = userService.getAppointUserAccountInfo(
                basicAccountModel.getAccount(),
                basicAccountModel.getSource());
        if (getUser == null) {
            log.warn("该账户{} 未在本平台进行注册, {}来源", basicAccountModel.getAccount(), basicAccountModel.getSource());
            throw new BusinessException(ResultHintConstant.LOGIN_ACCOUNT_NOT);
        }
        String pwd = AuthUtils.md5Hex(basicAccountModel.getPwd(), getUser.getSalt());
        if (!pwd.equals(getUser.getPwd())) {
            log.warn("密码错误!!");
            throw new BusinessException(ResultHintConstant.LOGIN_PWD_ERROR);
        }
        LoginSuccessModel loginSuccessModel = userGenerate.generateResultLoginSuccess(
                data.getCommon(),
                getUser,
                userService.getAppointUserSettingInfo(getUser.getId())
        );
        loginSuccess(getUser.getId(), data.getCommon());   // 登录成功发送消息队列
        return CommonResult.ok(loginSuccessModel);
    }

    @Operation(summary = "使用验证码进行登录")
    @RequestMapping(value = "useVerifyLogin", method = {RequestMethod.POST})
    @ResponseBody
    public CommonResult useVerifyLogin(@RequestBody CommonAskParam<BasicAccountModel> data) throws BusinessException {
        BasicAccountModel basicAccountModel = data.getData();
        UserModel getUser = userService.getAppointUserAccountInfo(
                basicAccountModel.getAccount(),
                basicAccountModel.getSource());
        if (getUser == null) {
            log.warn("验证码登录该账户{} 未在本平台进行注册, {}来源", basicAccountModel.getAccount(), basicAccountModel.getSource());
            throw new BusinessException(ResultHintConstant.LOGIN_ACCOUNT_NOT);
        }
        AccountVerifyCodeEnum verifyCodeEnum =AccountVerifyCodeEnum.VERIFY;
        String redisKey = verifyCodeEnum.getRedisKey() + basicAccountModel.getSource() + ":" + basicAccountModel.getAccount();
        String getRedisKeyContent = redisUtil.get(redisKey);
        if (StringUtil.isEmpty(getRedisKeyContent)) {
            log.warn("未找到{} 账户的注册验证码, 验证码失效或过期", basicAccountModel.getAccount());
            throw new BusinessException(ResultHintConstant.VERIFY_CODE_UNKNOWN);
        }
        if (!basicAccountModel.getPwd().equals(getRedisKeyContent)) {
            log.warn("错误验证码{}, 正确验证码{}", basicAccountModel.getPwd(), getRedisKeyContent);
            throw new BusinessException(ResultHintConstant.VERIFY_CODE_ERROR);
        }
        LoginSuccessModel loginSuccessModel = userGenerate.generateResultLoginSuccess(
                data.getCommon(),
                getUser,
                userService.getAppointUserSettingInfo(getUser.getId())
        );
        redisUtil.delete(redisKey);                          // 删除redis 中的验证码
        loginSuccess(getUser.getId(), data.getCommon());    // 登录成功发送消息队列
        return CommonResult.ok(loginSuccessModel);
    }

    @Operation(summary = "注册")
    @RequestMapping(value = "registerAccount", method = {RequestMethod.POST})
    @ResponseBody
    public CommonResult registerAccount(@RequestBody CommonAskParam<BasicAccountModel.RegisterModel> data) throws BusinessException {
        BasicAccountModel.RegisterModel registerModel = data.getData();
        UserModel getUser = userService.getAppointUserAccountInfo(
                registerModel.getAccount(),
                registerModel.getSource()
        );
        if (getUser != null) {
            log.warn("{}该账户已存在本系统", registerModel.getAccount());
            throw new BusinessException(ResultHintConstant.REGISTER_ACCOUNT_EXIST);
        }
        AccountVerifyCodeEnum verifyCodeEnum = AccountVerifyCodeEnum.REGISTER;
        String redisKey = verifyCodeEnum.getRedisKey() + registerModel.getSource() + ":" + registerModel.getAccount();
        String getRedisKeyContent = redisUtil.get(redisKey);
        if (StringUtil.isEmpty(getRedisKeyContent)) {
            log.warn("未找到{} 账户的注册验证码, 验证码失效或过期", registerModel.getAccount());
            throw new BusinessException(ResultHintConstant.VERIFY_CODE_UNKNOWN);
        }
        if (!registerModel.getVerifyCode().equals(getRedisKeyContent)) {
            log.warn("错误验证码{}, 正确验证码{}", registerModel.getVerifyCode(), getRedisKeyContent);
            throw new BusinessException(ResultHintConstant.VERIFY_CODE_ERROR);
        }
        LoginMethodEnum loginMethodEnum = LoginMethodEnum.getAppointLoginMethod(registerModel.getSource());
        // 生成用户基础信息
        UserModel newGenerate = userGenerate.generateUser(
                registerModel.getAccount(), registerModel.getPwd(), loginMethodEnum);
        // 注册
        userService.registerUser(
                newGenerate,
                userGenerate.generateUserSetting(
                        newGenerate.getId(),
                        registerModel.getName()
                )
        );
        redisUtil.delete(redisKey);
        return CommonResult.ok();
    }

    @Operation(summary = "三方登录")
    @RequestMapping(value = "authLogin", method = {RequestMethod.POST})
    @ResponseBody
    public CommonResult authLogin(@RequestBody CommonAskParam<UserAuthModel> data) throws BusinessException {
        UserAuthModel userAuthModel = data.getData();
        UserAuthModel getAuthModel = userService.getAppointSecretUserAuth(
                userAuthModel.getSecret(),
                userAuthModel.getChannel());
        if (getAuthModel == null) {
            log.warn("{}该三方账户未在系统中注册 与 绑定过", userAuthModel.getSecret());
            throw new BusinessException(ResultHintConstant.LOGIN_AUTH_UNBIND);
        }
        if (StringUtil.isEmpty(getAuthModel.getUser())) {
            log.warn("{}该三方账户未在系统中注册 与 绑定过", userAuthModel.getSecret());
            throw new BusinessException(ResultHintConstant.LOGIN_AUTH_UNBIND);
        }
        UserModel getUser = userService.getAppointIdAccountInfo(getAuthModel.getId());
        // 返回登录信息
        LoginSuccessModel loginSuccessModel = userGenerate.generateResultLoginSuccess(
                data.getCommon(),
                getUser,
                userService.getAppointUserSettingInfo(getUser.getId())
        );
        loginSuccess(getUser.getId(), data.getCommon());    // 登录成功发送消息队列
        return CommonResult.ok(loginSuccessModel);
    }

    @Operation(summary = "未在系统中注册的, 直接注册一个新的账户")
    @RequestMapping(value = "authLoginRegister", method = {RequestMethod.POST})
    @ResponseBody
    public CommonResult authLoginRegister(@RequestBody CommonAskParam<BasicAccountModel.AuthLoginRegisterModel> data) throws BusinessException {
        BasicAccountModel.AuthLoginRegisterModel authLoginModel = data.getData();
        UserAuthModel getAuthModel = userService.getAppointSecretUserAuth(
                authLoginModel.getSecret(),
                authLoginModel.getChannel());
        UserModel userModel = null;
        UserSettingModel userSettingModel = null;
        if (getAuthModel == null) {
            LoginMethodEnum loginMethodEnum = LoginMethodEnum.getAppointLoginMethod(authLoginModel.getChannel());
            userModel = userGenerate.generateUser(
                    authLoginModel.getThirdAccount(),
                    authLoginModel.getPwd(),
                    loginMethodEnum
            );
            userSettingModel = userGenerate.generateUserSetting(
                    userModel.getId(),
                    authLoginModel.getName()
            );
            // 三方登录后注册
            userService.authLoginRegisterUser(
                    userModel,
                    userGenerate.generateUserAuth(userModel.getId(), authLoginModel),
                    userSettingModel
            );
        } else {
            userModel = userService.getAppointIdAccountInfo(getAuthModel.getId());
            userSettingModel = userService.getAppointUserSettingInfo(getAuthModel.getId());
        }
        // 返回登录信息
        LoginSuccessModel loginSuccessModel = userGenerate.generateResultLoginSuccess(
                data.getCommon(),
                userModel,
                userSettingModel
        );
        return CommonResult.ok(loginSuccessModel);
    }


    @Operation(summary = "三方登录绑定账户")
    @RequestMapping(value = "authLoginBindAccount", method = {RequestMethod.POST})
    @ResponseBody
    public CommonResult authLoginBindAccount(@RequestBody CommonAskParam<BasicAccountModel.AuthLoginBindAccountModel> data) throws BusinessException {
        BasicAccountModel.AuthLoginBindAccountModel basicAccountModel = data.getData();
        UserModel userModel = userService.getAppointUserAccountInfo(basicAccountModel.getAccount(), basicAccountModel.getChannel());
        UserAuthModel userAuthModel = null;
        UserSettingModel userSettingModel = null;
        if (userModel == null) {
            if (StringUtil.isEmpty(basicAccountModel.getPwd())) {
                log.warn("系统中未有{}该账户信息, 需要未其设置一个新的账户信息, 必须设置其密码", basicAccountModel.getAccount());
                throw new BusinessException(ResultHintConstant.LOGIN_PWD_SETTING);
            }
            LoginMethodEnum loginMethodEnum = LoginMethodEnum.getAppointLoginMethod(basicAccountModel.getChannel());
            userModel = this.userGenerate.updateUserModelThirdAccount(
                    basicAccountModel.getThirdAccount(),
                    new UserModel().builder().id(userModel.getId()).build(),
                    loginMethodEnum
            );
            // 三方登录后注册
            userService.authLoginRegisterUser(
                    userModel,
                    userGenerate.generateUserAuth(userModel.getId(), basicAccountModel),
                    userSettingModel
            );
        } else {
            AccountVerifyCodeEnum verifyCodeEnum = AccountVerifyCodeEnum.VERIFY;
            String redisKey = verifyCodeEnum.getRedisKey() + basicAccountModel.getSource() + ":" + basicAccountModel.getAccount();
            String getRedisKeyContent = redisUtil.get(redisKey);
            if (StringUtil.isEmpty(getRedisKeyContent)) {
                log.warn("未找到{} 账户的注册验证码, 验证码失效或过期", basicAccountModel.getAccount());
                throw new BusinessException(ResultHintConstant.VERIFY_CODE_UNKNOWN);
            }
            if (!basicAccountModel.getPwd().equals(getRedisKeyContent)) {
                log.warn("错误验证码{}, 正确验证码{}", basicAccountModel.getPwd(), getRedisKeyContent);
                throw new BusinessException(ResultHintConstant.VERIFY_CODE_ERROR);
            }
            redisUtil.delete(redisKey);
            userAuthModel = userService.getAppointSecretUserAuth(basicAccountModel.getSecret(), basicAccountModel.getChannel());
            LoginMethodEnum loginMethodEnum = LoginMethodEnum.getAppointLoginMethod(basicAccountModel.getChannel());
            userModel = userGenerate.updateUserModelThirdAccount(
                    basicAccountModel.getSecret(),
                    new UserModel().builder()
                            .id(userModel.getId())
                            .build(),
                    loginMethodEnum);
            userService.authLoginBindUser(userAuthModel, userModel);
            userSettingModel = userService.getAppointUserSettingInfo(userModel.getId());
        }
        // 返回登录信息
        LoginSuccessModel loginSuccessModel = userGenerate.generateResultLoginSuccess(
                data.getCommon(),
                userModel,
                userSettingModel
        );
        loginSuccess(userModel.getId(), data.getCommon());    // 登录成功发送消息队列
        return CommonResult.ok(loginSuccessModel);
    }

    @Operation(summary = "忘记密码, 并进行修改")
    @RequestMapping(value = "forgetPwd", method = {RequestMethod.POST})
    @ResponseBody
    public CommonResult forgetPwd(@RequestBody CommonAskParam<BasicAccountModel.ForgetPassModel> data) throws BusinessException {
        BasicAccountModel.ForgetPassModel forgetPassModel = data.getData();
        UserModel getUser = userService.getAppointUserAccountInfo(
                forgetPassModel.getAccount(),
                forgetPassModel.getSource()
        );
        if (getUser == null) {
            log.warn("该账户{} 未在本平台进行注册, {}来源", forgetPassModel.getAccount(), forgetPassModel.getSource());
            throw new BusinessException(ResultHintConstant.LOGIN_ACCOUNT_NOT);
        }
        AccountVerifyCodeEnum verifyCodeEnum = AccountVerifyCodeEnum.FORGET_PWD;
        String redisKey = verifyCodeEnum.getRedisKey() + forgetPassModel.getSource() + ":" + forgetPassModel.getAccount();
        String getRedisKeyContent = redisUtil.get(redisKey);
        if (StringUtil.isEmpty(getRedisKeyContent)) {
            log.warn("未找到{} 账户的注册验证码, 验证码失效或过期", forgetPassModel.getAccount());
            throw new BusinessException(ResultHintConstant.VERIFY_CODE_UNKNOWN);
        }
        if (!forgetPassModel.getVerifyCode().equals(getRedisKeyContent)) {
            log.warn("错误验证码{}, 正确验证码{}", forgetPassModel.getVerifyCode(), getRedisKeyContent);
            throw new BusinessException(ResultHintConstant.VERIFY_CODE_ERROR);
        }
        userService.updateUserLoginPwd(getUser.getId(), forgetPassModel.getPwd());
        return CommonResult.ok();
    }
}
